package com.kmxd.ams.app.system;

import cn.hutool.core.bean.BeanUtil;
import cn.hutool.core.util.NumberUtil;
import cn.hutool.core.util.StrUtil;
import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
import com.baomidou.mybatisplus.core.toolkit.Wrappers;
import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
import com.kmxd.ams.client.system.ISysPostSvc;
import com.kmxd.ams.client.system.dto.SysPostAddDTO;
import com.kmxd.ams.client.system.dto.SysPostEditDTO;
import com.kmxd.ams.client.system.dto.SysPostQueryDTO;
import com.kmxd.ams.client.system.vo.SysPostListVO;
import com.kmxd.ams.client.system.vo.SysPostVO;
import com.kmxd.ams.core.common.constant.CacheConst;
import com.kmxd.ams.core.common.constant.ErrorCode;
import com.kmxd.ams.core.common.enums.StatusEnum;
import com.kmxd.ams.core.exception.BizTipException;
import com.kmxd.ams.core.util.IdUtil;
import com.kmxd.ams.infra.system.entity.SysPost;
import com.kmxd.ams.infra.system.entity.SysUserPost;
import com.kmxd.ams.infra.system.mapper.SysPostMapper;
import com.kmxd.ams.infra.system.mapper.SysUserPostMapper;
import java.util.List;
import java.util.Objects;
import java.util.Set;
import lombok.AllArgsConstructor;
import org.springframework.cache.annotation.CacheConfig;
import org.springframework.cache.annotation.CacheEvict;
import org.springframework.cache.annotation.Cacheable;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;

/**
 * 岗位表 服务实现类
 *
 * @author admin
 * @since 2021-06-22
 */
@Service
@AllArgsConstructor
@CacheConfig(cacheNames = CacheConst.CACHE_PREFIX_SYS_POST)
public class SysPostSvcImpl implements ISysPostSvc {

  private SysPostMapper sysPostMapper;

  private SysUserPostMapper sysUserPostMapper;

  @Cacheable(keyGenerator = "myKeyGenerator")
  @Override
  public Page<SysPostListVO> selectPage(Page reqPage, SysPostQueryDTO req) {
    LambdaQueryWrapper<SysPost> queryWrapper = Wrappers.lambdaQuery();
    queryWrapper.like(
        StrUtil.isNotBlank(req.getPostCode()), SysPost::getPostCode, req.getPostCode());
    queryWrapper.like(
        StrUtil.isNotBlank(req.getPostName()), SysPost::getPostName, req.getPostName());
    queryWrapper.orderByAsc(SysPost::getSort);
    Page<SysPost> page = sysPostMapper.selectPage(reqPage, queryWrapper);
    Page<SysPostListVO> voPage = BeanUtil.copyProperties(page, Page.class);
    voPage.setRecords(BeanUtil.copyToList(page.getRecords(), SysPostListVO.class));
    return voPage;
  }

  @Override
  public List<SysPostListVO> selectList(SysPostQueryDTO req) {
    LambdaQueryWrapper<SysPost> queryWrapper = Wrappers.lambdaQuery();
    queryWrapper.like(
        StrUtil.isNotBlank(req.getPostCode()), SysPost::getPostCode, req.getPostCode());
    queryWrapper.like(
        StrUtil.isNotBlank(req.getPostName()), SysPost::getPostName, req.getPostName());
    queryWrapper.orderByAsc(SysPost::getSort);
    List<SysPost> list = sysPostMapper.selectList(queryWrapper);
    return BeanUtil.copyToList(list, SysPostListVO.class);
  }

  @CacheEvict(allEntries = true)
  @Override
  @Transactional(rollbackFor = Exception.class)
  public void add(SysPostAddDTO req) {
    if (!this.checkUniquePostName(req.getPostName(), null)) {
      throw BizTipException.instance(ErrorCode.VALIDATE_ERROR, "岗位名称已存在");
    }
    if (!this.checkUniquePostCode(req.getPostCode(), null)) {
      throw BizTipException.instance(ErrorCode.VALIDATE_ERROR, "岗位编码已存在");
    }
    SysPost entity = BeanUtil.copyProperties(req, SysPost.class);
    sysPostMapper.insert(entity);
  }

  @CacheEvict(allEntries = true)
  @Override
  @Transactional(rollbackFor = Exception.class)
  public void edit(SysPostEditDTO req) {
    if (!this.checkUniquePostName(req.getPostName(), req.getId())) {
      throw BizTipException.instance(ErrorCode.VALIDATE_ERROR, "岗位名称已存在");
    }
    if (!this.checkUniquePostCode(req.getPostCode(), req.getId())) {
      throw BizTipException.instance(ErrorCode.VALIDATE_ERROR, "岗位编码已存在");
    }
    SysPost entity = BeanUtil.copyProperties(req, SysPost.class);
    sysPostMapper.updateById(entity);
  }

  @CacheEvict(allEntries = true)
  @Override
  @Transactional(rollbackFor = Exception.class)
  public void remove(String ids) {
    Set<Long> idList = IdUtil.split(ids);
    idList.forEach(
        item -> {
          SysPost sysPost = sysPostMapper.selectById(item);
          SysUserPost sysUserPost =
              sysUserPostMapper.selectOne(
                  Wrappers.lambdaQuery(SysUserPost.class).eq(SysUserPost::getPostId, item));
          if (Objects.nonNull(sysUserPost)) {
            throw BizTipException.instance(
                ErrorCode.VALIDATE_ERROR, String.format("岗位【%s】已被使用，无法删除", sysPost.getPostName()));
          }
        });
    idList.forEach(
        item -> {
          sysPostMapper.deleteById(item);
        });
  }

  @Cacheable(keyGenerator = "myKeyGenerator")
  @Override
  public SysPostVO view(Long id) {
    SysPost entity = sysPostMapper.selectById(id);
    return BeanUtil.copyProperties(entity, SysPostVO.class);
  }

  @Override
  public List<SysPostVO> listOptions() {
    List<SysPost> sysPostList =
        sysPostMapper.selectList(
            Wrappers.lambdaQuery(SysPost.class)
                .eq(SysPost::getStatus, StatusEnum.YES.getCode())
                .orderByAsc(SysPost::getSort));
    return BeanUtil.copyToList(sysPostList, SysPostVO.class);
  }

  @Override
  public List<SysPostVO> selectOptions() {
    List<SysPost> sysPostList =
        sysPostMapper.selectList(
            Wrappers.lambdaQuery(SysPost.class)
                .eq(SysPost::getStatus, StatusEnum.YES.getCode())
                .orderByAsc(SysPost::getSort));
    return BeanUtil.copyToList(sysPostList, SysPostVO.class);
  }

  private Boolean checkUniquePostCode(String value, Long id) {
    if (StrUtil.isBlank(value)) {
      return true;
    }
    id = Objects.isNull(id) ? -1L : id;
    SysPost entity =
        sysPostMapper.selectOne(
            Wrappers.lambdaQuery(SysPost.class).eq(SysPost::getPostCode, value));
    return Objects.isNull(entity) || NumberUtil.equals(entity.getId(), id);
  }

  private Boolean checkUniquePostName(String value, Long id) {
    if (StrUtil.isBlank(value)) {
      return true;
    }
    id = Objects.isNull(id) ? -1L : id;
    SysPost entity =
        sysPostMapper.selectOne(
            Wrappers.lambdaQuery(SysPost.class).eq(SysPost::getPostName, value));
    return Objects.isNull(entity) || NumberUtil.equals(entity.getId(), id);
  }
}
